﻿namespace PokerSimulator
{
	using System;

	public abstract class Game
	{
		private readonly Deck _deck;
		private int _gamesToPlay = 1;
		private HandCollection _hands;
		private Log _log;
		private int _maxCardsInHandCount;
		private int _maxPlayerCount = 22;
		private int _playerCount;
		private int _sharedCardsCount;
		private Hand _sharedHand;
		private int _startingCardsInHand;
		private bool _verboseLogging;

		protected Game()
		{
			_deck = new Deck();
			_log = new Log();
		}

		protected Game(int playerCount) : this()
		{
			PlayerCount = playerCount;
		}

		public Log Log
		{
			get { return _log; }
			set { _log = value; }
		}

		public int GamesToPlay
		{
			get { return _gamesToPlay; }
			set { _gamesToPlay = value; }
		}

		public bool VerboseLogging
		{
			get { return _verboseLogging; }
			set { _verboseLogging = value; }
		}

		protected int MaxPlayerCount
		{
			get { return _maxPlayerCount; }
			set { _maxPlayerCount = value; }
		}

		protected int StartingCardsInHand
		{
			get { return _startingCardsInHand; }
			set { _startingCardsInHand = value; }
		}

		protected int MaxCardsInHandCount
		{
			get { return _maxCardsInHandCount; }
			set { _maxCardsInHandCount = value; }
		}

		protected int SharedCardsCount
		{
			get { return _sharedCardsCount; }
			set { _sharedCardsCount = value; }
		}

		public Hand SharedHand
		{
			get { return _sharedHand; }
			set { _sharedHand = value; }
		}

		public int PlayerCount
		{
			get { return _playerCount; }
			set { _playerCount = value; }
		}

		protected Deck Deck
		{
			get { return _deck; }
		}

		public HandCollection Hands
		{
			get { return _hands; }
		}


		public static Game Create(GameType gameType, int playerCount)
		{
			Game game;
			switch (gameType)
			{
				case GameType.TexasHoldEm:
					game = new TexasHoldEmGame(playerCount);
					break;
				case GameType.FiveCardShowdown:
					game = new FiveCardShowdown(playerCount);
					break;
				default:
					throw new ArgumentException("Yuo can has no valid gaim tipe");
			}
			return game;
		}

		protected void MakeHands()
		{
			_hands = new HandCollection(PlayerCount);
			SharedHand = new Hand();
		}

		public virtual Log Run() // aka Go() in python version
		{
			int gamesToPlay = GamesToPlay;
			for (int round = 0; round < gamesToPlay; round++)
			{
				RunGame();
			}
			return _log;
		}

		private void RunGame()
		{
			Deal();
			UpdateLog();
			NewRound();
		}


		protected virtual void ReportGame()
		{
			throw new NotImplementedException();
		}

		protected virtual void PrintReportHeader()
		{
			throw new NotImplementedException();
		}

		protected virtual void NewRound()
		{
			_deck.Shuffle();
			MakeHands();
		}

		protected virtual void UpdateLog()
		{
			Log.AddHands(_hands);
		}

		protected virtual void Deal()
		{
			throw new NotImplementedException();
		}


		public virtual void PrintSummary()
		{
			throw new NotImplementedException();
		}


		internal static void ReportGame(Game game)
		{
			Log.PrintReportHeader(game);
			Log.Report(game.Log);
		}
	}
}